home *** CD-ROM | disk | FTP | other *** search
/ The Programmer Disk / The Programmer Disk (Microforum).iso / xpro / extra / pro13 / tsr.doc < prev    next >
Text File  |  1993-09-04  |  61KB  |  809 lines

  1.     ------------------------------------------------------------------------
  2.     |                                                                      |
  3.     |                                                                      |
  4.     |                                                                      |
  5.     |                                                                      |
  6.     |                                                                      |
  7.     |                                                                      |
  8.     |                                                                      |
  9.     |                                                                      |
  10.     |                                                                      |
  11.     |                                                                      |
  12.     |                                                                      |
  13.     |                                                                      |
  14.     |                                                                      |
  15.     |                                                                      |
  16.     |                                                                      |
  17.     |                                                                      |
  18.     |                                                                      |
  19.     |                                                                      |
  20.     |                                                                      |
  21.     |                                                                      |
  22.     |                                                                      |
  23.     |                                                                      |
  24.     |                                 T S R                                |
  25.     |                                                                      |
  26.     |                              Version 1.5                             |
  27.     |                                                                      |
  28.     |                Copyright (C) 1993, Geoff Friesen B.Sc.               |
  29.     |                         All rights reserved.                         |
  30.     |                                                                      |
  31.     |                                                                      |
  32.     |                                                                      |
  33.     |                                                                      |
  34.     |                                                                      |
  35.     |                                                                      |
  36.     |                                                                      |
  37.     |                                                                      |
  38.     |                                                                      |
  39.     |                                                                      |
  40.     |                                                                      |
  41.     |                                                                      |
  42.     |                                                                      |
  43.     |                                                                      |
  44.     |                                                                      |
  45.     |                                                                      |
  46.     |                                                                      |
  47.     |                                                                      |
  48.     |                                                                      |
  49.     |                                                                      |
  50.     |                                                                      |
  51.     |                                                                      |
  52.     ------------------------------------------------------------------------
  53.  
  54.     ------------------------------------------------------------------------
  55.     |                                                                      |
  56.     |                                History                               |
  57.     |                                -------                               |
  58.     |                                                                      |
  59.     | TSR TOOLKIT has a long history.  I first became interested in build- |
  60.     | ing TSRs back in the fall of 1988.  I tried building a few but found |
  61.     | the amount of work involved very tiring.  If I had a nickle for each |
  62.     | time I had to reboot the computer while testing, I could retire.  It |
  63.     | became apparent that some mechanism was needed to handle TSR details |
  64.     | allowing me to concentrate on the application.  This would save alot |
  65.     | of time.  In 1989, I put together my first toolkit.  I pre-wrote the |
  66.     | resident and installation kernels.  The library was in object form   |
  67.     | and could quickly be linked with the application module.  Although   |
  68.     | this technique worked and saved alot of time, it was pretty bloated. |
  69.     | There were other problems as well.  After giving up on the toolkit   |
  70.     | for a few years, I decided to take one last crack in 1992.  I began  |
  71.     | development work on TSR TOOLKIT.  TSR TOOLKIT has gone through alot  |
  72.     | of versions.  Version 1.5 is the latest and the most complete.  For  |
  73.     | the first time, this toolkit feels like a winner.  I am very glad to |
  74.     | be able to share this package with you and hope that you will find   |
  75.     | it useful in writing your own TSRs.                                  |
  76.     |                                                                      |
  77.     |                                                                      |
  78.     |                                                                      |
  79.     |                                                                      |
  80.     |                                                                      |
  81.     |                                                                      |
  82.     |                                                                      |
  83.     |                                                                      |
  84.     |                                                                      |
  85.     |                                                                      |
  86.     |                                                                      |
  87.     |                                                                      |
  88.     |                                                                      |
  89.     |                                                                      |
  90.     |                                                                      |
  91.     |                                                                      |
  92.     |                                                                      |
  93.     |                                                                      |
  94.     |                                                                      |
  95.     |                                                                      |
  96.     |                                                                      |
  97.     |                                                                      |
  98.     |                                                                      |
  99.     |                                                                      |
  100.     |                                                                      |
  101.     |                                                                      |
  102.     |                                                                      |
  103.     |                                                                      |
  104.     |                                                                      |
  105.     ------------------------------------------------------------------------
  106.                       - 2 -
  107.  
  108.     ------------------------------------------------------------------------
  109.     |                                                                      |
  110.     |                             TSR Structure                            |
  111.     |                             -------------                            |
  112.     |                                                                      |
  113.     | Before you can write your own TSRs, it would be a good idea to get   |
  114.     | comfortable with the internal structure.  In this section, I want to |
  115.     | explain how the kernels work and how everything fits together.  You  |
  116.     | can examine the source code when you create a TSR (or look at TSR.C) |
  117.     | for additional information.  Let's start with a diagram.             |
  118.     |                                                                      |
  119.     |  ----------------                                                    |
  120.     |  |   RESIDENT   |                                                    |
  121.     |  |    KERNEL    |                                                    |
  122.     |  ----------------                                                    |
  123.     |  |  APPLICATION |                                                    |
  124.     |  ----------------                                                    |
  125.     |  | INSTALLATION |                                                    |
  126.     |  |    KERNEL    |                                                    |
  127.     |  ----------------                                                    |
  128.     |                                                                      |
  129.     | This is as basic as it gets.  A TSR is structured as a .COM format   |
  130.     | program.  Internally, a TSR resembles a sandwich.  The resident and  |
  131.     | installation kernels surround the application.  When you create a    |
  132.     | TSR, you can focus your attention on creating this application.  The |
  133.     | kernels have already been written for you.  The option does exist to |
  134.     | extend the installation kernel to add customization to your program. |
  135.     | We'll see this later on in this document.                            |
  136.     |                                                                      |
  137.     | The resident kernel has one basic goal.  It must respond to hotkey   |
  138.     | presses, delay activation until the computer system is in a stable   |
  139.     | state, and then perform a launch sequence.  The launch sequence is   |
  140.     | sort of equivalent to the start up code in a regular application.    |
  141.     | The stack is switched, registers are saved and then initialized as   |
  142.     | appropriate, interrupt vectors are saved, the keyboard buffer is     |
  143.     | emptied, and other tasks are performed prior to calling the main ()  |
  144.     | function (the entry point) within the application.  Once main () has |
  145.     | returned to the launch sequence, everything is restored and the TSR  |
  146.     | exits as if the hotkey had never been pressed.                       |
  147.     |                                                                      |
  148.     | The basic goal behind the installation kernel is to install the TSR  |
  149.     | once and only once and provide a means to remove the TSR (uninstall) |
  150.     | when necessary.                                                      |
  151.     |                                                                      |
  152.     | Over the years, these kernels have grown in size and capability.     |
  153.     | They perform a staggering amount of work.  In order to really under- |
  154.     | stand how TSRs work, we're going to have to look in detail at these  |
  155.     | kernels.  Here we go.                                                |
  156.     |                                                                      |
  157.     |                                                                      |
  158.     |                                                                      |
  159.     ------------------------------------------------------------------------
  160.                       - 3 -
  161.  
  162.     ------------------------------------------------------------------------
  163.     |                                                                      |
  164.     | When a TSR is loaded into memory, execution begins at address 100h   |
  165.     | because the TSR is a .COM program.  The JMP instruction at 100h will |
  166.     | cause execution to continue at the first address in the installation |
  167.     | kernel.                                                              |
  168.     |                                                                      |
  169.     | The personal identification section (aka communications API) follows |
  170.     | the JMP instruction.  The communications API is a collection of use- |
  171.     | ful pieces of information organized in a standard manner and access- |
  172.     | ible to other TSRs and regular programs.  The first piece of infor-  |
  173.     | mation is the hotkey character.  This is the ASCII letter or digit   |
  174.     | of the default hotkey.  The equivalent scancode follows.  Following  |
  175.     | a NULL byte is the version number.  The version number was designed  |
  176.     | to make it easy to change the kernel structure for subsequent ver-   |
  177.     | sions of TSR TOOLKIT without crashing previously written TSRs and    |
  178.     | regular programs which access the kernel.  All versions prior to 1.4 |
  179.     | have version number zero.  Version zero should not be considered as  |
  180.     | a reliable means of identifying different kernel locations since I   |
  181.     | made a number of changes without changing this number.  Version 1.4  |
  182.     | has version number 1.  Version 1.5 has version number 2.  These num- |
  183.     | bers are stored in binary in a single byte.  The address of the main |
  184.     | procedure follows.  I have not encountered a use for this knowledge  |
  185.     | as yet but will undoubtedly find a use in the future.  The starting  |
  186.     | address of the installation kernel follows.  Again, this information |
  187.     | is present but not being used at this time.  A two-byte field marked |
  188.     | "reserved" follows.  I may use this field in the future to extend    |
  189.     | the communications API past the signature field which follows.  The  |
  190.     | signature identifies the TSR and always starts with "TSR:".  The sig |
  191.     | is stored as an ASCIZ string (a C-style string with a terminating 0  |
  192.     | byte).                                                               |
  193.     |                                                                      |
  194.     | The resident data section follows the communications API.  All data  |
  195.     | storage required by the resident kernel is located in this section.  |
  196.     | The beep flag variable (beepf) is really part of the communications  |
  197.     | API (even though this is not indicated).  This variable will always  |
  198.     | following the terminating 0 byte of the signature.                   |
  199.     |                                                                      |
  200.     | The resident code section follows the data section.  This section is |
  201.     | divided into a variety of redirected interrupt vectors, the launch   |
  202.     | sequence procedure, the sound API, the XMS API, and the stack.       |
  203.     |                                                                      |
  204.     | Interrupt 9 is activated whenever a hotkey is pressed.  If the TSR   |
  205.     | is not already active (as indicated by the tsr_state variable then   |
  206.     | interrupt 9 sets this variable to a TRIGGERED status.  Interrupt 9   |
  207.     | will also generate a beep if the beep flag (beepf) is set.  The pur- |
  208.     | pose of this beep is to provide positive assurance to the user that  |
  209.     | the hotkey has been acknowledged.  Sometimes a TSR may not activate  |
  210.     | immediately when its hotkey is pressed for the following reasons.    |
  211.     |                                                                      |
  212.     |                                                                      |
  213.     ------------------------------------------------------------------------
  214.                       - 4 -
  215.  
  216.     ------------------------------------------------------------------------
  217.     |                                                                      |
  218.     | DOS may not be in a stable state.  The extended memory manager found |
  219.     | in HIMEM.SYS may not be in a stable state.  The BIOS disk service    |
  220.     | (interrupt 13h) may be active.  The chaining order of installed TSRs |
  221.     | may be such that a TSR cannot activate until a currently active TSR  |
  222.     | becomes inactive.                                                    |
  223.     |                                                                      |
  224.     | Interrupts 8 and 28h monitor tsr_state.  Interrupt 8, the timer tick |
  225.     | interrupt, activates about 18.2 times per second (unless the timer   |
  226.     | frequency has been changed).  Interrupt 28h is called repeatedly by  |
  227.     | the DOS buffered keyboard input function (function 10) when DOS is   |
  228.     | waiting for input at the command line (a function code such as 10 is |
  229.     | placed in the AH register and interrupt 21h is called to request DOS |
  230.     | perform a function such as buffered keyboard input).  When DOS is    |
  231.     | waiting for a command at the command line, DOS is active but is in a |
  232.     | state where it is safe to call DOS functions higher than 12.         |
  233.     |                                                                      |
  234.     | When interrupts 8 and 28h detect that tsr_state has been set to the  |
  235.     | TRIGGERED status, they perform four tests to ensure that everything  |
  236.     | is as stable as possible.  The first test is to make sure that the   |
  237.     | critical error handler is not active.  The second is to ensure that  |
  238.     | DOS is not operating in a critical section.  The third is to be cer- |
  239.     | tain that interrupt 13h is not active.  The fourth and final test is |
  240.     | to make certain that HIMEM.SYS is not active.  If all four tests are |
  241.     | passed then the launch sequence procedure is called to complete the  |
  242.     | activation.                                                          |
  243.     |                                                                      |
  244.     | Interrupt 13h is redirected to monitor itself by setting a flag upon |
  245.     | input and resetting this flag upon output.  Interrupts 8 and 28h use |
  246.     | this flag in testing to see if it is safe to activate.               |
  247.     |                                                                      |
  248.     | Interrupts 1bh and 23h have also been redirected but only by the     |
  249.     | launch sequence procedure.  This was done to ensure an even higher   |
  250.     | degree of reliability in the event that CTRL-BREAK should be pressed |
  251.     | when a standard I/O function is called (not a console I/O function   |
  252.     | whose code is less than 13).                                         |
  253.     |                                                                      |
  254.     | The reason why TSR TOOLKIT does not support any version of DOS less  |
  255.     | than 3.30 has to do with the critical error handler interrupt.  This |
  256.     | interrupt has been set to return a FAIL code whenever called.  Doing |
  257.     | this ensures that you never need to include a critical error handler |
  258.     | in your application.  DOS 3.30 was the first version of DOS to offer |
  259.     | a FAIL code which always causes the offending interrupt 21h function |
  260.     | to return to the application with a suitable error code in the AX    |
  261.     | register.                                                            |
  262.     |                                                                      |
  263.     |                                                                      |
  264.     |                                                                      |
  265.     |                                                                      |
  266.     |                                                                      |
  267.     ------------------------------------------------------------------------
  268.                       - 5 -
  269.  
  270.     ------------------------------------------------------------------------
  271.     |                                                                      |
  272.     | The multiplex interrupt needs to be redirected as well.  When 4310h  |
  273.     | is passed in the AX register, interrupt 2fh responds with the entry  |
  274.     | address to the HIMEM.SYS XMS handler (if HIMEM.SYS is installed).    |
  275.     | One of the tests performed by interrupts 8 and 28h is to ensure that |
  276.     | HIMEM.SYS is not active when a TSR activates.  It turns out that the |
  277.     | XMS handler is not reentrant.  By redirecting interrupt 2fh, we can  |
  278.     | pass a different entry point address.  This new handler (see the XMS |
  279.     | XMS_rdriver procedure) can set a flag upon entry, call the handler,  |
  280.     | and reset the flag upon exit allowing interrupts 8 and 28h to carry  |
  281.     | out their test.                                                      |
  282.     |                                                                      |
  283.     | The launch sequence procedure is called by either interrupt 8 and    |
  284.     | 28h to complete the activation process.  This procedure must setup   |
  285.     | an appropriate environment so that the application can execute in a  |
  286.     | completely safe environment.  The first step is to switch stacks.  A |
  287.     | stack follows this procedure.  There is no telling what stack will   |
  288.     | be in use when the launch sequence procedure begins execution.  This |
  289.     | stack could have room for several hundred to several thousand bytes. |
  290.     | On the other hand, there may only be enough room for a handful.  Our |
  291.     | application needs its own stack.  Who knows how many local variables |
  292.     | will be defined.  The launch sequence procedure switches back to the |
  293.     | original stack just before it exits.  All registers are saved on the |
  294.     | switched stack since any could be modified.  Interrupts are enabled  |
  295.     | and the string move direction flag in the processor flags register   |
  296.     | is cleared to ensure that any string instructions accessed by the    |
  297.     | application will operate in a forward manner.  The data segment (DS) |
  298.     | register is set to the same segment as the code segment (since the   |
  299.     | application is written in C, it will be accessing static data via    |
  300.     | its DGROUP which has its address set to the data segment address).   |
  301.     | Interrupts 1bh, 23h, and 24h are redirected for greater reliability. |
  302.     | Interrupt 24h is the critical error handler interrupt.  The program  |
  303.     | segment prefix (PSP) of the currently active application (or TSR)    |
  304.     | which we are interrupting is saved and then set to our PSP.  The     |
  305.     | same thing happens to the data transfer area (DTA).  Extended error  |
  306.     | information is also saved.  Whenever a DOS function is called and an |
  307.     | error occurs, information is saved constituting the extended error   |
  308.     | state.  This tells us more about what error occurred and where it    |
  309.     | occurred.  We now come to the strangest section of the launch seq-   |
  310.     | uence procedure.  In this section, we redirect interrupts 8, 9, 16h, |
  311.     | and 1ch.  We actually set them to values that they had before the    |
  312.     | TSR was installed.  I would rather not have done this but it turns   |
  313.     | out that various Microsoft programs including DOS 5.0 EDIT/QBASIC    |
  314.     | and Microsoft Word 5.0 crash when a TSR is activated with these ints |
  315.     | redirected.  Go figure Microsoft.  The unfortunate part about this   |
  316.     | is you cannot take advantage of the kernel's interrupt 8 to add some |
  317.     | additional timing code for creating timers.  You must install your   |
  318.     | own.  Finally, we flush the keystroke buffer, disconnect the speaker |
  319.     | and hide the mouse cursor.  We then call the application main ()     |
  320.     | function and restore everything to its original state prior to exit. |
  321.     ------------------------------------------------------------------------
  322.                       - 6 -
  323.  
  324.     ------------------------------------------------------------------------
  325.     |                                                                      |
  326.     | The SOUND API follows.  This API provides four functions that your   |
  327.     | application can use to take advantage of sound and processor speed-  |
  328.     | independent timing.  These functions are documented in a separate    |
  329.     | section.                                                             |
  330.     |                                                                      |
  331.     | The XMS API follows the SOUND API and contains a group of functions  |
  332.     | that your application can call to access extended memory.  These     |
  333.     | functions are documented in a separate section.                      |
  334.     |                                                                      |
  335.     | The resident code section and the resident kernel conclude with the  |
  336.     | stack.  The stack follows the XMS API and builds down towards it.  I |
  337.     | chose a default stack size of 256 bytes but you have the option of   |
  338.     | increasing the stack as will be seen later.                          |
  339.     |                                                                      |
  340.     | The application code follows the stack.  The code comprising EXTRA.  |
  341.     | ASM (if specified) would be loaded following the application.        |
  342.     |                                                                      |
  343.     | The installation kernel begins with the installation data section.   |
  344.     | This section contains all of the data local to this section.  The    |
  345.     | command tail address is used by the command tail parsing logic to    |
  346.     | locate the next parse location on the command tail.  The psp is used |
  347.     | to refer to the segment of a resident TSR.  The scancodes table is   |
  348.     | used to convert a hotkey letter read from the command tail to an     |
  349.     | equivalent scancode which will be stored in the communications API.  |
  350.     | A variety of messages along with a variable to hold the major por-   |
  351.     | tion of the DOS version number complete this section.                |
  352.     |                                                                      |
  353.     | The first piece of code has the task of displaying the TSR title.    |
  354.     | This gives you the ability to personalize your TSR.  The TSR title   |
  355.     | is actually stored in your application .C file.  The examples found  |
  356.     | in TSREX.ZIP show how the title would be formatted.  Every line must |
  357.     | end with a carriage return/line feed sequence.                       |
  358.     |                                                                      |
  359.     | The next step is to obtain the DOS version number and make sure that |
  360.     | the version is at least 3.30 (because of the critical error handler  |
  361.     | FAIL code).  We save the major portion in the ver variable so we can |
  362.     | access this later (HIMEM.SYS was only introduced with DOS 5.0 and so |
  363.     | we cannot redirect the multiplex interrupt if our DOS version is not |
  364.     | 5.0 or higher).                                                      |
  365.     |                                                                      |
  366.     | We obtain the addresses of the critical error and critical section   |
  367.     | flags since these must be tested by interrupts 8 and 28h as part of  |
  368.     | the task in ensuring that DOS is stable.                             |
  369.     |                                                                      |
  370.     | The next step is to search for a previously installed copy (it would |
  371.     | be wasteful of memory to install more than one copy).  The search is |
  372.     | also important when we wish to uninstall (if the TSR has not been    |
  373.     | installed then how can we uninstall).                                |
  374.     |                                                                      |
  375.     ------------------------------------------------------------------------
  376.                       - 7 -
  377.  
  378.     ------------------------------------------------------------------------
  379.     |                                                                      |
  380.     | Command tail parsing follows.  The command tail is stored in the PSP |
  381.     | at offset 81h.  The last byte in the command tail must be a carriage |
  382.     | return character.  We skip leading whitespace (blanks and tabs) and  |
  383.     | then parse the first nonwhitespace character.  This character can be |
  384.     | only a carriage return or a forward slash (/).  If a carriage return |
  385.     | then parsing is finished.  We would then display the current hotkey  |
  386.     | status and exit if this is a second install attempt or continue with |
  387.     | the install logic.  If this is a slash then we check for either a B, |
  388.     | K, or U character immediately following.  The B character indicates  |
  389.     | that we want to set the BEEP state.  The K character indicates that  |
  390.     | we want to set the HOTKEY.  The U character indicates that we want   |
  391.     | to UNINSTALL.  If B is selected then we parse the next character     |
  392.     | following the B (must be 0 for disable or 1 for enable) and save it. |
  393.     | If K is selected then we parse the next character following the K    |
  394.     | (must be A-Z or 0-9 - a-z is converted to A-Z) and save it.  In the  |
  395.     | event of B or K as the command option, we continue parsing.  If U is |
  396.     | selected then we check to see if a copy of this TSR already exists.  |
  397.     | If it does then we attempt to uninstall.  Otherwise, we display an   |
  398.     | error message and exit.                                              |
  399.     |                                                                      |
  400.     | A call to an xparse () function defined in the application will fol- |
  401.     | low if this extension option is specified.  This gives the applica-  |
  402.     | tion the ability to extend command tail parsing.  Numerous examples  |
  403.     | of this can be found in TSREX.ZIP.  This function returns nonzero if |
  404.     | an error is detected during the extended parse.  Otherwise, command  |
  405.     | tail parsing resumes.  The B, K, and U options will always override  |
  406.     | any equivalent options defined in xparse ().  Therefore, they will   |
  407.     | never be passed to xparse () and there is no point in trying to use  |
  408.     | them.                                                                |
  409.     |                                                                      |
  410.     | The next step is application-specific.  Some applications may need   |
  411.     | to perform additional setup such as redirecting other interrupt vec- |
  412.     | tors.  If this is the case then the installation kernel would call a |
  413.     | setup () function defined in the application.  The setup () function |
  414.     | returns nonzero if an error is detected.                             |
  415.     |                                                                      |
  416.     | The next part of the install logic is to redirect the HIMEM.SYS XMS  |
  417.     | handler if the current version of DOS is 5.0 or higher and HIMEM.SYS |
  418.     | has been installed.                                                  |
  419.     |                                                                      |
  420.     | Interrupts 8, 9, 13h, 28h, and 2fh are redirected.  Note that inter- |
  421.     | rupt 9 is redirected last to ensure that all other interrupts are    |
  422.     | installed in case the hotkey is pressed before we finish the instal- |
  423.     | lation.  At the same time, the environment segment is freed.  Note   |
  424.     | that we obtain the current addresses of interrupt 16h and 1ch.  The  |
  425.     | launch sequence procedure requires this information.                 |
  426.     |                                                                      |
  427.     | Finally, we calculate the amount of memory (in paragraphs) to keep   |
  428.     | and terminate but stay resident.                                     |
  429.     ------------------------------------------------------------------------
  430.                       - 8 -
  431.  
  432.     ------------------------------------------------------------------------
  433.     |                                                                      |
  434.     | It would be instructive to take a look at the uninstall procedure.   |
  435.     | The first step is to ensure that interrupts 8, 9, 13h, 28h, and 2fh  |
  436.     | match their saved addresses.  We cannot uninstall if any different   |
  437.     | address is detected.  This would indicate that the TSR is not the    |
  438.     | most recently installed.  If all interrupts match then we restore    |
  439.     | them to their saved addresses.  We then attempt to call cleanup ()   |
  440.     | in the application (if defined for the application).  Any addtional  |
  441.     | redirected interrupts would be restored as well as any other cleanup |
  442.     | tasks.  A nonzero value is returned if cleanup is unsuccessful.  In  |
  443.     | previous versions of TSR TOOLKIT, no value was returned.  This fea-  |
  444.     | ture has been added to version 1.5 to ensure a more reliable kernel. |
  445.     | We attempt to release all memory previously allocated when we TSRed. |
  446.     | If cleanup is unsuccessful or we cannot release this memory then we  |
  447.     | display a reboot error message and exit.  Otherwise we display a     |
  448.     | success message and exit.                                            |
  449.     |                                                                      |
  450.     |                                                                      |
  451.     |                                                                      |
  452.     |                                                                      |
  453.     |                                                                      |
  454.     |                                                                      |
  455.     |                                                                      |
  456.     |                                                                      |
  457.     |                                                                      |
  458.     |                                                                      |
  459.     |                                                                      |
  460.     |                                                                      |
  461.     |                                                                      |
  462.     |                                                                      |
  463.     |                                                                      |
  464.     |                                                                      |
  465.     |                                                                      |
  466.     |                                                                      |
  467.     |                                                                      |
  468.     |                                                                      |
  469.     |                                                                      |
  470.     |                                                                      |
  471.     |                                                                      |
  472.     |                                                                      |
  473.     |                                                                      |
  474.     |                                                                      |
  475.     |                                                                      |
  476.     |                                                                      |
  477.     |                                                                      |
  478.     |                                                                      |
  479.     |                                                                      |
  480.     |                                                                      |
  481.     |                                                                      |
  482.     |                                                                      |
  483.     ------------------------------------------------------------------------
  484.                       - 9 -
  485.  
  486.     ------------------------------------------------------------------------
  487.     |                                                                      |
  488.     |                               Sound API                              |
  489.     |                               ---------                              |
  490.     |                                                                      |
  491.     | * void beep (void);                                                  |
  492.     |                                                                      |
  493.     | Generate a beep for 1/3 of a second.                                 |
  494.     |                                                                      |
  495.     | * void nosound (void);                                               |
  496.     |                                                                      |
  497.     | Disable sound.                                                       |
  498.     |                                                                      |
  499.     | * void pause (unsigned ticks);                                       |
  500.     |                                                                      |
  501.     | Generate a delay in timer ticks.  By default, the tick rate is 18.2  |
  502.     | ticks per second (approximately).  The minimum value passed to this  |
  503.     | function should be 1 tick otherwise you might be waiting for a very  |
  504.     | long time.  There is the possibility, due to the unpredictability of |
  505.     | when a timer interrupt occurs that you may lose one tick.  I have    |
  506.     | not come up with any solution to this problem.                       |
  507.     |                                                                      |
  508.     | * void sound (unsigned frequency);                                   |
  509.     |                                                                      |
  510.     | Enable sound at the specified frequency.  The lowest valid frequency |
  511.     | is 19 Hertz.  Any lower value and sound () immediately exits.        |
  512.     |                                                                      |
  513.     |                                                                      |
  514.     | These functions are prototyped in TSRLIB.H (see TSRLIB.ZIP).         |
  515.     |                                                                      |
  516.     |                                                                      |
  517.     |                                                                      |
  518.     |                                                                      |
  519.     |                                                                      |
  520.     |                                                                      |
  521.     |                                                                      |
  522.     |                                                                      |
  523.     |                                                                      |
  524.     |                                                                      |
  525.     |                                                                      |
  526.     |                                                                      |
  527.     |                                                                      |
  528.     |                                                                      |
  529.     |                                                                      |
  530.     |                                                                      |
  531.     |                                                                      |
  532.     |                                                                      |
  533.     |                                                                      |
  534.     |                                                                      |
  535.     |                                                                      |
  536.     |                                                                      |
  537.     ------------------------------------------------------------------------
  538.                      - 10 -
  539.  
  540.     ------------------------------------------------------------------------
  541.     |                                                                      |
  542.     |                                XMS API                               |
  543.     |                                -------                               |
  544.     |                                                                      |
  545.     | One of the best things added to DOS 5.0, as far as I am concerned,   |
  546.     | was HIMEM.SYS.  At last, a decent gateway to extended memory.  TSR   |
  547.     | TOOLKIT takes advantage of this capability.                          |
  548.     |                                                                      |
  549.     | typedef struct                                                       |
  550.     |         {                                                            |
  551.     |            long length;                                              |
  552.     |            unsigned srchandle;                                       |
  553.     |            long srcoffset;                                           |
  554.     |            unsigned desthandle;                                      |
  555.     |            long destoffset;                                          |
  556.     |         }                                                            |
  557.     |         EMMS; /* Extended Memory Move Structure */                   |
  558.     |                                                                      |
  559.     | * int XMS_Alloc (unsigned nkilos);                                   |
  560.     |                                                                      |
  561.     | Attempt to allocate a block of extended memory in kilobytes.  If no  |
  562.     | error occurs then a handle is returned.  This handle references the  |
  563.     | extended memory region indirectly.  If an error occurs then zero is  |
  564.     | returned.                                                            |
  565.     |                                                                      |
  566.     | * int XMS_Copy (EMMS *x);                                            |
  567.     |                                                                      |
  568.     | This function allows you to copy a block of conventional memory to   |
  569.     | extended memory or the other way around.  You need to create an EMMS |
  570.     | variable and fill it in appropriately.  The length specifies the     |
  571.     | number of bytes to copy and must be an even number.  The handles     |
  572.     | cannot come from locked extended memory blocks.  If zero is the han- |
  573.     | dle then the offset field would specify the segment:offset address   |
  574.     | in conventional memory where the block starts.  Zero is returned on  |
  575.     | failure.  See XMS.C in TSREX.ZIP for an example.                     |
  576.     |                                                                      |
  577.     | * int XMS_Exists (void);                                             |
  578.     |                                                                      |
  579.     | This function returns a nonzero value if HIMEM.SYS is not installed. |
  580.     |                                                                      |
  581.     | * int XMS_Free (unsigned handle);                                    |
  582.     |                                                                      |
  583.     | This function frees a previously allocated block.  It returns zero   |
  584.     | on failure.                                                          |
  585.     |                                                                      |
  586.     |                                                                      |
  587.     |                                                                      |
  588.     |                                                                      |
  589.     |                                                                      |
  590.     |                                                                      |
  591.     ------------------------------------------------------------------------
  592.                      - 11 -
  593.  
  594.     ------------------------------------------------------------------------
  595.     |                                                                      |
  596.     | * long XMS_Lock (unsigned handle);                                   |
  597.     |                                                                      |
  598.     | This function attempts to lock a memory block to a specific address. |
  599.     | If successful then the 32-bit linear address of this block will be   |
  600.     | returned.  Zero is returned otherwise.  This allows you to work with |
  601.     | this block directly via the BIOS int 15h facility.                   |
  602.     |                                                                      |
  603.     | * int XMS_Query (unsigned *nkilos, unsigned *maxblocksize);          |
  604.     |                                                                      |
  605.     | This function returns the total number of kilobytes of available     |
  606.     | extended memory in *nkilos and the size of the largest block in      |
  607.     | *maxblocksize.  Both values take the high memory area (HMA) which is |
  608.     | 64K in length into account.  Zero is returned on error.              |
  609.     |                                                                      |
  610.     | * int XMS_Realloc (unsigned handle, unsigned nkilos);                |
  611.     |                                                                      |
  612.     | This function allows you to adust the size of a memory block.  Zero  |
  613.     | is returned on error.                                                |
  614.     |                                                                      |
  615.     | * int XMS_Unlock (unsigned handle);                                  |
  616.     |                                                                      |
  617.     | This function performs the inverse of XMS_Lock ().  Zero is returned |
  618.     | on error.                                                            |
  619.     |                                                                      |
  620.     |                                                                      |
  621.     | These functions are prototyped in TSRLIB.H (see TSRLIB.ZIP).         |
  622.     |                                                                      |
  623.     |                                                                      |
  624.     |                                                                      |
  625.     |                                                                      |
  626.     |                                                                      |
  627.     |                                                                      |
  628.     |                                                                      |
  629.     |                                                                      |
  630.     |                                                                      |
  631.     |                                                                      |
  632.     |                                                                      |
  633.     |                                                                      |
  634.     |                                                                      |
  635.     |                                                                      |
  636.     |                                                                      |
  637.     |                                                                      |
  638.     |                                                                      |
  639.     |                                                                      |
  640.     |                                                                      |
  641.     |                                                                      |
  642.     |                                                                      |
  643.     |                                                                      |
  644.     |                                                                      |
  645.     ------------------------------------------------------------------------
  646.                      - 12 -
  647.  
  648.     ------------------------------------------------------------------------
  649.     |                                                                      |
  650.     |                              Install API                             |
  651.     |                              -----------                             |
  652.     |                                                                      |
  653.     | * int cleanup (void);                                                |
  654.     |                                                                      |
  655.     | This is the prototype for the cleanup () function which must be      |
  656.     | defined in the application source file if you decide to incorporate  |
  657.     | setup/cleanup.  A nonzero value must be returned on error or zero on |
  658.     | success.                                                             |
  659.     |                                                                      |
  660.     | * int parse (void);                                                  |
  661.     |                                                                      |
  662.     | This function returns the next character on the command tail.  The   |
  663.     | parse position is updated unless a carriage return is returned.      |
  664.     |                                                                      |
  665.     | * void setcseg (void);                                               |
  666.     |                                                                      |
  667.     | This function sets both the DS and ES registers to the current seg-  |
  668.     | ment (the same segment as CS) and is used with xparse ().            |
  669.     |                                                                      |
  670.     | * void setrseg (void);                                               |
  671.     |                                                                      |
  672.     | This function sets both the DS and ES registers to the resident seg- |
  673.     | ment and is used with xparse ().                                     |
  674.     |                                                                      |
  675.     | * int setup (void);                                                  |
  676.     |                                                                      |
  677.     | This is the prototype for the setup () function which must be        |
  678.     | defined in the application source file if you decide to incorporate  |
  679.     | setup/cleanup.  A nonzero value must be returned on error or zero on |
  680.     | success.                                                             |
  681.     |                                                                      |
  682.     | * void skipws (void);                                                |
  683.     |                                                                      |
  684.     | This function skips leading whitespace on the command tail.  White-  |
  685.     | space consists of blanks and tabs.                                   |
  686.     |                                                                      |
  687.     | * void unparse (void);                                               |
  688.     |                                                                      |
  689.     | This function backs up the parse pointer by one position unless the  |
  690.     | pointer is pointing to a carriage return.                            |
  691.     |                                                                      |
  692.     | * int xparse (int option);                                           |
  693.     |                                                                      |
  694.     | This is the prototype for the xparse () function which must be       |
  695.     | defined in the application source file if you decide to incorporate  |
  696.     | extended parsing.  The option passed is the character which follows  |
  697.     | the / on the command tail.  A nonzero value must be returned on      |
  698.     | error or zero on success.                                            |
  699.     ------------------------------------------------------------------------
  700.                      - 13 -
  701.  
  702.     ------------------------------------------------------------------------
  703.     |                                                                      |
  704.     |                                 Tools                                |
  705.     |                                 -----                                |
  706.     |                                                                      |
  707.     | TSR TOOLKIT provides two utility programs and a batch file that work |
  708.     | together with BCC.EXE, TASM.EXE, and TLINK.EXE to generate TSRs from |
  709.     | C source files.                                                      |
  710.     |                                                                      |
  711.     | T.BAT serves as the crux.  It calls all other programs in a proper   |
  712.     | sequence.  The format of the T command line is:                      |
  713.     |                                                                      |
  714.     | T filename arguments                                                 |
  715.     |                                                                      |
  716.     | The filename consists of the TSR .C name with an optional drive and  |
  717.     | path.  A file extension must not be specified since T.BAT appends a  |
  718.     | .C to the filename.                                                  |
  719.     |                                                                      |
  720.     | The arguments which will shortly be discussed consist of either a -  |
  721.     | or / character followed by a sequence of characters.  Each argument  |
  722.     | must be separated by whitespace (blanks and/or tabs).  These argu-   |
  723.     | ments may appear in any order but must follow the file name.         |
  724.     |                                                                      |
  725.     | * -hx                                                                |
  726.     |                                                                      |
  727.     | h is the hotkey argument.  Any letter A-Z or digit 0-9 may appear in |
  728.     | place of the x.  This letter/digit when combined with ALT serves as  |
  729.     | the default hotkey.                                                  |
  730.     |                                                                      |
  731.     | * -i                                                                 |
  732.     |                                                                      |
  733.     | i is the include argument.  This argument causes the contents of     |
  734.     | EXTRA.ASM to be included after the application code.                 |
  735.     |                                                                      |
  736.     | * -sy                                                                |
  737.     |                                                                      |
  738.     | s is the stack argument.  This argument specifies the size of the    |
  739.     | TSR stack (y ranges from the default of 256 to 8192 bytes).          |
  740.     |                                                                      |
  741.     | * -sc                                                                |
  742.     |                                                                      |
  743.     | sc is the setup/cleanup argument.  This argument allows the instal-  |
  744.     | lation kernel to incorporate calls to setup () and cleanup ().  They |
  745.     | must be defined in the application source file.                      |
  746.     |                                                                      |
  747.     | * -x                                                                 |
  748.     |                                                                      |
  749.     | x is the xparse argument.  This argument allows the installation     |
  750.     | kernel to incorporate a call to xparse ().  This must be defined in  |
  751.     | the application source file.                                         |
  752.     |                                                                      |
  753.     ------------------------------------------------------------------------
  754.                      - 14 -
  755.  
  756.     ------------------------------------------------------------------------
  757.     |                                                                      |
  758.     | What does T.BAT do?  After parsing the command line, it calls the    |
  759.     | BCC.EXE program to compile the application .C file and create an     |
  760.     | equivalent assembler source file (via the -S switch).  At this time, |
  761.     | the TI environment variable is passed to BCC.EXE telling it where to |
  762.     | find the TSRLIB source files should any be referenced in the app.    |
  763.     | If everything is successful then FILTER.EXE is called.  BCC.EXE will |
  764.     | generate a file with an .ASM extension which is the equivalent of    |
  765.     | the .C file.  However, this file is not in a format suitable for     |
  766.     | turning into a TSR.  FILTER.EXE takes this .ASM file and turns it    |
  767.     | into a properly formatted file with a .TSR extension.  This is then  |
  768.     | passed to TSR.EXE which creates a sandwich .ASM file.  The .TSR file |
  769.     | is placed between the resident and installation kernels.  Once this  |
  770.     | has been accomplished, the resulting .ASM file is assembled and then |
  771.     | linked.  TLINK.EXE creates a .COM file directly.  If any errors are  |
  772.     | detected during any step then T.BAT displays an error message and    |
  773.     | aborts.                                                              |
  774.     |                                                                      |
  775.     | Note that TSR.EXE takes identical arguments as T.BAT but in reverse  |
  776.     | order.  Don't let that be a point of confusion.  Always use T.BAT.   |
  777.     | Each example program (see TSREX.ZIP) shows the calling sequence via  |
  778.     | T.BAT in the comments section at the start of the source file.       |
  779.     |                                                                      |
  780.     |                                                                      |
  781.     |                                                                      |
  782.     |                                                                      |
  783.     |                                                                      |
  784.     |                                                                      |
  785.     |                                                                      |
  786.     |                                                                      |
  787.     |                                                                      |
  788.     |                                                                      |
  789.     |                                                                      |
  790.     |                                                                      |
  791.     |                                                                      |
  792.     |                                                                      |
  793.     |                                                                      |
  794.     |                                                                      |
  795.     |                                                                      |
  796.     |                                                                      |
  797.     |                                                                      |
  798.     |                                                                      |
  799.     |                                                                      |
  800.     |                                                                      |
  801.     |                                                                      |
  802.     |                                                                      |
  803.     |                                                                      |
  804.     |                                                                      |
  805.     |                                                                      |
  806.     |                                                                      |
  807.     ------------------------------------------------------------------------
  808.                      - 15 -
  809.